package cn.ffcs.util.ftp;

import java.io.*;
import java.net.*;
import java.util.*;

public class FTPSearch extends Thread
{
    String _host;
    static final int PORT = 21;
    ServerSocket ss;
    Socket _ds;
    Socket _sc;
    PrintStream _out;
    String _hostAddress;
    BufferedReader _in;
    BufferedReader _dataIn;
    String _reply;
    protected StringBuffer _log = new StringBuffer(10000);
    Vector _result;
    String _user;
    String _pass;

    public FTPSearch(String ip, String user, String pass)
    {
        _host = ip;
        _user = user;
        _pass = pass;
        _result = new Vector();
    }

    public FTPSearch(String ip)
    {
        _host = ip;
        _user = "anonymous";
        _pass = "name_zm@sohu.com";
        _result = new Vector();
    }

    protected boolean login() throws UnknownHostException, IOException
    {
        boolean successful = false;
        StringBuffer reply = new StringBuffer();
        _sc = new Socket(_host, PORT);
        _hostAddress = _sc.getLocalAddress().getHostAddress().replace('.', ',');
        _sc.setSoTimeout(15000);
        _out = new PrintStream(_sc.getOutputStream(), true);
        _in = new BufferedReader(new InputStreamReader(_sc.getInputStream()));
        reply.append(readReply().trim());
        if (reply.toString().startsWith("220"))
            if (comm("USER " + _user))
                if (comm("PASS " + _pass)) successful = true;
        comm("TYPE A");
        return successful;
    }

    protected String getCurrentDir() throws IOException
    {
        String currentDir = null;
        if (comm("PWD"))
        {
            StringTokenizer st = new StringTokenizer(_reply);
            st.nextToken();
            StringBuffer rtDir = new StringBuffer(st.nextToken());
            currentDir = rtDir.substring(1, rtDir.length() - 1);
        }
        return currentDir;
    }

    public void search() throws IOException, InterruptedException
    {
        try
        {
            for (int i = 0; i < 5; i++)
            {
                if (login()) break;
                System.out.println("Wait 10 seconds to try again...");
                sleep(10000);
            }
            scan();
            logout();
        }
        catch (IOException ex)
        {

        }
        finally
        {
            PrintStream out = new PrintStream(new FileOutputStream("Log.txt"));
            out.println(_log);
            out.close();
            printResult("result.txt");
        }

    }

    protected void scan() throws IOException
    {
        Vector fileNames = new Vector();
        tellPort();
        comm("LIST -R");

        // Get data_connection's InputStream.
        try
        {
            _ds = ss.accept();
            System.out.println(ss.toString());
        }
        catch (IOException ex)
        {
            ss.close();
        }
        _dataIn = new BufferedReader(
                new InputStreamReader(_ds.getInputStream()));

        System.out.println("Scanning now.Please waiting......");
        // Read directory content
        try
        {
            String temp = "";
            do
            {
                temp = _dataIn.readLine();
                if (temp == null) break;
                fileNames.add(temp);

            }
            while (temp != null);
        }
        catch (InterruptedIOException ex)
        {
            System.out.println("Caught InterruptedIOException1:" + ex);
        }

        // Read end infomation
        try
        {
            do
            {
                String temp = _in.readLine();
                _log.append(temp + "r");
                System.out.println(temp);
            }
            while (_in.ready());
        }
        catch (InterruptedIOException ex)
        {
            System.out.println("Caught InterruptedIOException2:" + ex);
        }
        _result = fileNames;
    }

    public Vector getResult()
    {
        return _result;
    }

    public StringBuffer getLog()
    {
        return _log;
    }

    public static Vector parse() throws FileNotFoundException, IOException
    {
        Vector result = new Vector();
        FileInputStream fileIn = new FileInputStream("result.txt");
        BufferedReader fReader = new BufferedReader(new InputStreamReader(
                fileIn));
        // int size=fileIn.available();
        // System.out.println(String.valueOf(size));
        String dir = "/";
        System.out.println("Parsing now.Please wait......");
        while (fReader.ready())
        {
            String temp = fReader.readLine();
            StringTokenizer tt = new StringTokenizer(temp);

            if (tt.countTokens() == 1)
            {
                if (temp.startsWith("/"))
                    dir = temp.replace(':', ' ').trim() + "/";
                else
                    dir = "/" + temp.replace(':', ' ').trim() + "/"; // parseResult
                                                                     // .
                                                                     // add(dir)
                                                                     // ;
                                                                     // continue
                                                                     // ;
            }
            if ((!temp.equals(""))
                    && (temp.startsWith("-") || temp.startsWith("b")
                            || temp.startsWith("c") || temp.startsWith("l")))
            {
                for (int i = 0; i < 4; i++)
                    tt.nextToken();
                String description = "";
                for (int i = 0; i < 4; i++)
                    description = description + tt.nextToken() + " ";
                String cont = "";
                do
                {
                    cont = cont + tt.nextToken() + " ";
                }
                while (tt.hasMoreTokens());
                result.add(new FileInfo(dir + cont.trim(), description.trim()));
                continue;
            }
            else if (temp.startsWith("d"))
            {
                for (int i = 0; i < 4; i++)
                    tt.nextToken();
                String description = "";
                for (int i = 0; i < 4; i++)
                    description = description + tt.nextToken() + " ";
                String cont = "";
                do
                {
                    cont = cont + tt.nextToken() + " ";
                }
                while (tt.hasMoreTokens());
                result.add(new FileInfo(dir + cont.trim() + "/", description
                        .trim()));
                continue;
            }
            else if (temp.equals(""))
            {
                continue;
            }
        }
        return result;
    }

    protected void logout() throws IOException
    {
        comm("QUIT");
    }

    protected void printResult(String resultFile) throws IOException
    {
        PrintStream out = new PrintStream(new FileOutputStream(resultFile));
        int len = _result.size();
        for (int i = 0; i < len; i++)
        {
            out.println(_result.elementAt(i));
        }
        out.close();
    }

    protected boolean comm(String command) throws IOException
    {
        boolean success = false;
        _out.println(command);
        System.out.println("<COMMAND>" + command);
        _log.append("<COMMAND>" + command + "r");
        _reply = readReply();
        if (command.startsWith("USER"))
        {
            success = _reply.startsWith("331") ? true : false;
        }
        else if (command.startsWith("PASS"))
        {
            success = _reply.startsWith("230") ? true : false;
            try
            {
                readReply();
            }
            catch (InterruptedIOException ex)
            {
            }
        }
        else if (command.equals("TYPE A"))
        {
            success = _reply.startsWith("200") ? true : false;
        }
        else if (command.startsWith("PORT"))
        {
            success = _reply.startsWith("200") ? true : false;
        }
        else if (command.startsWith("LIST"))
        {
            success = _reply.startsWith("150") ? true : false;
        }
        else if (command.startsWith("NLST"))
        {
            success = _reply.startsWith("150") ? true : false;
        }
        else if (command.equals("PWD"))
        {
            success = _reply.startsWith("257") ? true : false;
        }
        else if (command.startsWith("STAT"))
        {
            success = _reply.startsWith("211") ? true : false;
        }
        else if (command.equals("SYST"))
        {
            success = _reply.startsWith("215") ? true : false;
        }
        else if (command.startsWith("SITE"))
        {
            success = _reply.startsWith("214") ? true : false;
        }
        else if (command.equals("QUIT"))
        {
            success = _reply.startsWith("221") ? true : false;
        }
        return success;
    }

    public static void printVector(Vector vct)
    {
        int size = vct.size();
        for (int i = 0; i < size; i++)
        {
            System.out.println(vct.elementAt(i));
        }
    }

    protected String readReply() throws IOException, InterruptedIOException
    {
        StringBuffer reply = new StringBuffer();
        do
        {
            reply.append(_in.readLine() + "r");
        }
        while (_in.ready());
        System.out.println(reply);
        _log.append(reply);
        _reply = reply.toString();
        return _reply;
    }

    private int getDataPort()
    {
        int port = _sc.getLocalPort() + 1;
        return port;
    }

    private void tellPort() throws IOException
    {

        try
        {
            int port = getDataPort();
            System.out.println("Get data port:" + port);
            int x = (int) Math.round((port / 256) - 0.5);
            int y = port - x * 256;
            try
            {
                ss = new ServerSocket(port);
            }
            catch (IOException ex)
            {
                System.out
                        .println("IOException in Method tellPort() in Class ftpc--"
                                + ex);
            }
            comm("PORT " + _hostAddress + "," + x + "," + y);
        }
        finally
        {

        }
    }

    public static void main(String arg[])
    {
        try
        {
            FTPSearch client = new FTPSearch("202.114.2.2");
            client.search();
            client.parse();
        }
        catch (Exception ex)
        {
            System.out.println(ex);
        }
    }

}
